//Pascale Vacher - March 12
//OOP Assignment Semester 2

#include "TransactionList.h"

//---------------------------------------------------------------------------
//TransactionList: class implementation
//---------------------------------------------------------------------------

//____public member functions

//____constructors & destructors

//____other public member functions

void TransactionList::addNewTransaction( const Transaction& tr) {
    listOfTransactions_.addInFront( tr);
}
const Transaction TransactionList::newestTransaction() const {
    return (listOfTransactions_.first());
}
TransactionList TransactionList::olderTransactions() const {
	TransactionList trlist( *this);
    trlist.deleteFirstTransaction();
    return trlist;
}
void TransactionList::deleteFirstTransaction() {
    listOfTransactions_.deleteFirst();
}
void TransactionList::deleteGivenTransaction( const Transaction& tr) {
    listOfTransactions_.deleteOne( tr);
}
void TransactionList::deleteTransactionsUpToDate( const Date date) {
	TransactionList trl, temp( *this);

	while ( temp.size() != 0 ){
		if(  !(temp.newestTransaction().getDate() < date || temp.newestTransaction().getDate() == date))
			trl.addNewTransaction( temp.newestTransaction() );
		temp.deleteFirstTransaction();
	}
	(*this)=trl;
}
int TransactionList::size() const {
    return (listOfTransactions_.length());
}
const string TransactionList::toFormattedString() const {
//return transaction list as a (formatted) string
	ostringstream os_transactionlist;
    TransactionList tempTrList( *this);
	while ( ! ( tempTrList.size() == 0))
    {
		os_transactionlist << tempTrList.newestTransaction().toFormattedString() << endl;
        tempTrList.deleteFirstTransaction();
    }
	return ( os_transactionlist.str());
}

double TransactionList::getTotalTransactions() const {
	if ( size() == 0 )
		return 0;
	else {
		TransactionList temp( *this);
		double total( 0.0);

		while ( temp.size() != 0 ){
			Transaction tr( temp.newestTransaction());
			total = total + tr.getAmount();
			temp.deleteFirstTransaction();
		}
		return total;
	}
}
double TransactionList::getTotalTransactionsRecursive() const {
	if ( size() == 0 )
		return 0;
	else {
		return newestTransaction().getAmount() + olderTransactions().getTotalTransactionsRecursive();
	}
}
TransactionList TransactionList::getMostRecentTransactions(const int n){
	TransactionList trl, temp( *this);

	int j( n);
	if (temp.size() < j)
		j = temp.size(); //if the list is less than n, only loop until the end of the list.
	for ( int i( 0); i < j; ++i)
	{
		trl.addNewTransaction( temp.newestTransaction());
		temp.deleteFirstTransaction();
	}
	return trl;
}

TransactionList TransactionList::getAllDepositTransactions() const{
	TransactionList trl, temp( *this);

	while ( temp.size() != 0 ){
		if( temp.newestTransaction().getAmount() > 0 )
			trl.addNewTransaction( temp.newestTransaction() );
		temp.deleteFirstTransaction();
	}
	return trl;
}


/* ******NEEDS TO BE FINISHED*****
TransactionList TransactionList::getAllDepositTransactionsRecursive() const{
	if( size() == 0 )
		
	else {
		if ( newestTransaction().getAmount() > 0 )
			return newestTransaction().getAmount() + olderTransactions().getAllDepositTransactionsRecursive();
		else
			
	}
}*/

TransactionList TransactionList::getTransactionsForAmount( const double amount) {
	TransactionList trl, temp( *this);

	while ( temp.size() != 0 ){
		if( temp.newestTransaction().getAmount() == amount )
			trl.addNewTransaction( temp.newestTransaction() );
		temp.deleteFirstTransaction();
	}
	return trl;
}
TransactionList TransactionList::getTransactionsByTitle( const string title) {
	TransactionList trl, temp( *this);

	while ( temp.size() != 0 ){
		if( temp.newestTransaction().getTitle().find(title) != string::npos)
			trl.addNewTransaction( temp.newestTransaction() );
		temp.deleteFirstTransaction();
	}
	return trl;
}
TransactionList TransactionList::getTransactionsByDate( const string date){
	TransactionList trl, temp( *this);

	while ( temp.size() != 0 ){
		if( temp.newestTransaction().getDate().toFormattedString() == date )
			trl.addNewTransaction( temp.newestTransaction() );
		temp.deleteFirstTransaction();
	}
	return trl;
}
TransactionList TransactionList::getTransactionsUpToDate( const Date date){
	TransactionList trl, temp( *this);

	while ( temp.size() != 0 ){
		if( temp.newestTransaction().getDate() < date || temp.newestTransaction().getDate() == date)
			trl.addNewTransaction( temp.newestTransaction() );
		temp.deleteFirstTransaction();
	}
	return trl;
}

ostream& TransactionList::putDataInStream( ostream& os) const {
//put (unformatted) transaction list into an output stream
    TransactionList tempTrList( *this);
	while ( ! ( tempTrList.size() == 0))
    {
		os << tempTrList.newestTransaction() << endl;
        tempTrList.deleteFirstTransaction();
    }
	return os;
}
istream& TransactionList::getDataFromStream( istream& is) {
//read in (unformatted) transaction list from input stream
	Transaction aTransaction;
	is >> aTransaction;	//read first transaction
	while ( is != 0) 	//while not end of file
	{
		listOfTransactions_.addAtEnd( aTransaction);   //add transaction to list of transactions
		is >> aTransaction;	//read in next transaction
	}
	return is;
}


//---------------------------------------------------------------------------
//non-member operator functions
//---------------------------------------------------------------------------

ostream& operator<<( ostream& os, const TransactionList& aTransactionList) {
    return ( aTransactionList.putDataInStream( os));
}
istream& operator>>( istream& is, TransactionList& aTransactionList) {
	return ( aTransactionList.getDataFromStream( is));
}
